from django.shortcuts import render
from django.db.models import Q
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from rest_framework import mixins
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler  # 生成验证令牌
from rest_framework import permissions
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication

from users.models import UserProfile, VerifyCode
from .serializesr import SmsSerializesr, UserRegSerializesr, UserDetailsSerializesr
from utils.yunpian import YunPian
from utils.utils import ParturitionCode
from utils.permissions import IsOwnerOrReadOnly
# 获取User模型
User = get_user_model()
from utils.alipay import AliPays


class CustomBackend(ModelBackend):  # 新建CustomBackend类继承
    """
    注册成功后加密密码保存
    """

    # 重写该方加密密码
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:  # 查询数据库里是否
            # 查询用户名或手机号
            user = UserProfile.objects.get(Q(username=username) | Q(mobile=username))
            # 前端传来的是明文要加密密码
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class SmsCodeViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    获取手机验证码
    """
    # 序列化
    serializer_class = SmsSerializesr

    def create(self, request, *args, **kwargs):
        # 表单数据在request.data里
        serializer = self.get_serializer(data=request.data)  # get_serializer获取序列化表单并填入数据
        # 验证表单
        serializer.is_valid(raise_exception=True)  # raise_exception=True 验证失败直接抛异常
        # 从验证完成的serializer中获取mobile
        mobile = serializer.validated_data["mobile"]  # 数据在validated_data中
        code = ParturitionCode.random_figure()
        # 发送验证码
        is_sms = YunPian.send_sms(code, mobile)

        if is_sms != 0:
            # 发送失败返回错误信息和对应状态码
            return Response({"mobile": "错误信息"}, status=status.HTTP_400_BAD_REQUEST)

        else:
            # 发送成功保存信息
            vc = VerifyCode(code=code, mobile=mobile)
            vc.save()
            return Response({"mobile": mobile}, status=status.HTTP_201_CREATED)




class UserRegViewSet(mixins.CreateModelMixin,mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    create:
        用户注册
    retrieve:
        用户信息获取
    update:
        用户信息修改
    """

    queryset = UserProfile.objects.all()   #填充用户数据

    # 登陆验证方式JWT,持久化验证方式SA
    authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication)
    #动态获取serializer_class序列化模型
    def get_serializer_class(self):
        if self.action == 'retrieve':   #判断请求方式
            # 请求用户详情返回详情的Serializesr
            return UserDetailsSerializesr
        elif self.action == 'create':
            # 返回注册用户是Serializesr
            return UserRegSerializesr
        return UserDetailsSerializesr           #其他情况默认返回用户详情


    # 根据请求内容获取动态返回相应请求
    def get_permissions(self):
        if self.action == 'retrieve':   #判断请求方式
            # 如果是获取用户详情的请求就需要登陆才能获取，反回验证是否登陆
            return [permissions.IsAuthenticated()]
        elif self.action == 'create':
            #如果是创建用户请求就返回空数组，不需要任何权限
            return []
        return []           #警告这个返回必写

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = self.perform_create(serializer)  # 获取用户
        re_dict = serializer.data
        payload = jwt_payload_handler(user)  # 生成数据
        re_dict["token"] = jwt_encode_handler(payload)  # 注意这里token要和前端保持一致，

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) #注册成功返回

    def perform_create(self, serializer):
        serializer.save()

    #重写get_object，返回当前用户
    def get_object(self):
        return self.request.user




